package zack.project.domain.award.service;

import zack.project.domain.award.adapter.repository.IAwardRepository;
import zack.project.domain.award.model.aggregate.UserAwardRecordAggregate;
import zack.project.domain.award.event.SendAwardMessageEvent;
import zack.project.domain.award.model.entity.DistributeAwardEntity;
import zack.project.domain.award.model.entity.TaskEntity;
import zack.project.domain.award.model.entity.UserAwardRecordEntity;
import zack.project.domain.award.model.valobj.TaskStateVO;
import zack.project.domain.award.service.distribute.IDistributeAward;
import zack.project.types.event.BaseEvent;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.Map;

/**
 * @author A1793
 */
@Slf4j
@Service
public class AwardService implements IAwardService {


    private final IAwardRepository awardRepository;

    private final SendAwardMessageEvent sendAwardMessageEvent;
    //策略模式, <节点名,发奖节点>
    private final Map<String, IDistributeAward> distributeAwardMap;

    public AwardService(IAwardRepository awardRepository, SendAwardMessageEvent sendAwardMessageEvent, Map<String, IDistributeAward> distributeAwardMap) {

        this.awardRepository = awardRepository;
        this.sendAwardMessageEvent = sendAwardMessageEvent;
        this.distributeAwardMap = distributeAwardMap;
    }

    /**
     * 构建发奖的补偿任务，保存中奖记录{user_raffle_record}，更新用户抽奖单
     * @param userAwardRecordEntity
     */
    @Override
    public void saveUserAwardRecord(UserAwardRecordEntity userAwardRecordEntity) {
        //先生成消息的内容,设置奖品信息和抽奖单单号
        SendAwardMessageEvent.SendAwardMessage sendAwardMessage = new SendAwardMessageEvent.SendAwardMessage();
        sendAwardMessage.setAwardId(userAwardRecordEntity.getAwardId());
        sendAwardMessage.setUserId(userAwardRecordEntity.getUserId());
        sendAwardMessage.setAwardTitle(userAwardRecordEntity.getAwardTitle());
        sendAwardMessage.setOrderId(userAwardRecordEntity.getOrderId());
        sendAwardMessage.setAwardConfig(userAwardRecordEntity.getAwardConfig());

        //通过消息事件来构建统一的消息体，均为BaseEvent.EventMessage<T>的消息内容，{int code，String info，T data}
        BaseEvent.EventMessage<SendAwardMessageEvent.SendAwardMessage> sendAwardMessageEventMessage =
                sendAwardMessageEvent.buildEventMessage(sendAwardMessage);

        //创建任务实体，因为是发奖模块，
        // 所以message类型就是BaseEvent.EventMessage<SendAwardMessageEvent.SendAwardMessage>
        TaskEntity taskEntity = new TaskEntity();
        taskEntity.setUserId(userAwardRecordEntity.getUserId());
        taskEntity.setTopic(sendAwardMessageEvent.topic());
        taskEntity.setMessage(sendAwardMessageEventMessage);
        taskEntity.setMessageId(sendAwardMessageEventMessage.getId());
        taskEntity.setState(TaskStateVO.create);

        //创建中奖的聚合实体传递给仓储层做事务操作，保存奖品信息和发奖任务
        UserAwardRecordAggregate userAwardRecordAggregate = new UserAwardRecordAggregate();
        userAwardRecordAggregate.setUserAwardRecordEntity(userAwardRecordEntity);
        userAwardRecordAggregate.setTaskEntity(taskEntity);
        //保存中奖记录(更新数据库表{user_raffle_award})和发奖的任务(该任务是为了防止本方法中发送消息失败的补偿任务，更新数据库表{task})，
        //更新抽奖单状态为used(更新库表{user_raffle_order}) 并 向SendAwardCustomer监听的消息队列投入发奖消息
        awardRepository.saveUserAwardRecord(userAwardRecordAggregate);
        log.info("中奖记录保存完成 userId:{} orderId:{}", userAwardRecordEntity.getUserId(), userAwardRecordEntity.getOrderId());

    }



    @Override
    public void distributeAward(DistributeAwardEntity distributeAwardEntity) {
        //查询奖品id去数据库表{award}查询对应奖品awardKey
        //id    award_id        award_key               award_value     award_desc
        //1	    101	    user_credit_random	1,100	        用户积分【优先透彻规则范围，如果没有则走配置】	2023-12-09 11:07:06	2023-12-09 11:21:31
        //2	    102	    openai_use_count	5	            OpenAI 增加使用次数	2023-12-09 11:07:06	2023-12-09 11:12:59
        //3	    103	    openai_use_count	10	            OpenAI 增加使用次数	2023-12-09 11:07:06	2023-12-09 11:12:59
        String awardKey =
                awardRepository.queryAwardKey(distributeAwardEntity.getAwardId());

        if (StringUtils.isBlank(awardKey)) {
            log.error("分发奖品，奖品ID不存在。awardKey:{}", awardKey);
            return;
        }
        //根据这个奖品key去找对应的发奖节点
        IDistributeAward iDistributeAward = distributeAwardMap.get(awardKey);
        if (iDistributeAward == null) {
            log.error("分发奖品，对应的服务不存在。awardKey:{}", awardKey);
            throw new RuntimeException("分发奖品，奖品" + awardKey + "对应的服务不存在");
        }
        //发奖节点执行发奖流程
        iDistributeAward.giveOutPrize(distributeAwardEntity);
    }

    @Override
    public String queryAwardConfig(Integer awardId) {
        return awardRepository.queryAwardConfig(awardId);
    }

}
